{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 线上测试集模型融合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import division\n",
    "from __future__ import print_function\n",
    "\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import pickle\n",
    "import os\n",
    "import sys\n",
    "import time \n",
    "\n",
    "\n",
    "# 求 softmax\n",
    "def _softmax(score):\n",
    "    \"\"\"对一个样本的输出类别概率进行 softmax 归一化.\n",
    "    score: arr.shape=[1999].\n",
    "    \"\"\"\n",
    "    max_sc = np.max(score)   # 最大分数\n",
    "    score = score - max_sc\n",
    "    exp_sc = np.exp(score)\n",
    "    sum_exp_sc = np.sum(exp_sc)\n",
    "    softmax_sc = exp_sc / sum_exp_sc\n",
    "    return softmax_sc    # 归一化的结果\n",
    "    \n",
    "def softmax(scores):\n",
    "    \"\"\"对所有样本的输出概率进行 softmax 归一化处理。\n",
    "    scores: arr.shape=[n_sample, 1999].\n",
    "    \"\"\"\n",
    "    softmax_scs = map(_softmax, scores)\n",
    "    return np.asarray(softmax_scs)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 模型求加权平均\n",
    "这里的所有模型以及相应的权重是通过 local-ensemble 中对线下验证集进行权重调整得到的最好结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "37 37\n",
      "All 37 models\n",
      "1/37, scores_name=p1-1-bigru-512.npy\n",
      "2/37, scores_name=p1-2-bigru-512-true.npy\n",
      "3/37, scores_name=textcnn-fc-drop-title-content-256-3457-drop0.5.npy\n",
      "4/37, scores_name=f1-1-cnn-256-23457-11.npy\n",
      "5/37, scores_name=han-cnn-title-content-256-345.npy\n",
      "6/37, scores_name=han-cnn-title-content-256-23457-1234.npy\n",
      "7/37, scores_name=m7-rnn-cnn-256-100.npy\n",
      "8/37, scores_name=p2-1-rnn-cnn-256-256.npy\n",
      "9/37, scores_name=p3-2-cnn-256-2357.npy\n",
      "10/37, scores_name=p3-cnn-512-23457.npy\n",
      "11/37, scores_name=textcnn-fc-drop-title-content-256-345.npy\n",
      "12/37, scores_name=textcnn-fc-drop-title-content-256-3457-drop0.2.npy\n",
      "13/37, scores_name=m9-han-bigru-title-content-512-30.npy\n",
      "14/37, scores_name=m9-2-han-bigru-title-content-512-30.npy\n",
      "15/37, scores_name=han-bigru-title-content-256-30.npy\n",
      "16/37, scores_name=m8-han-bigru-256-30.npy\n",
      "17/37, scores_name=attention-bigru-title-content-256.npy\n",
      "18/37, scores_name=m7-2-rnn-cnn-128-100.npy\n",
      "19/37, scores_name=textcnn-fc-title-content-256-345.npy\n",
      "20/37, scores_name=m1-2-fasttext-topicinfo.npy\n",
      "21/37, scores_name=ch3-1-cnn-256-2345.npy\n",
      "22/37, scores_name=ch3-2-cnn-256-23457.npy\n",
      "23/37, scores_name=ch4-1-han-bigru-256-52.npy\n",
      "24/37, scores_name=ch5-1-2embed-rnn256-cnn2345.npy\n",
      "25/37, scores_name=p4-1-han-bigru-256.npy\n",
      "26/37, scores_name=ch6-1-han-cnn-2345-1234.npy\n",
      "27/37, scores_name=p5-1-2embed-rnn256-cnn2345.npy\n",
      "28/37, scores_name=ch5-2-2embed-rnn512-cnn3457.npy\n",
      "29/37, scores_name=c1-1-cnn-max-256-23457.npy\n",
      "30/37, scores_name=c1-2-cnn-256-345710.npy\n",
      "31/37, scores_name=c2-1-bigru-256.npy\n",
      "32/37, scores_name=textcnn-fc-drop-title-content-256-345-cross3cross0.npy\n",
      "33/37, scores_name=textcnn-fc-drop-title-content-256-345-cross3cross1.npy\n",
      "34/37, scores_name=textcnn-fc-drop-title-content-256-345-cross3cross2.npy\n",
      "35/37, scores_name=p3-3-cnn-max-256-345710.npy\n",
      "36/37, scores_name=textcnn-title-256-len50.npy\n",
      "37/37, scores_name=ch7-1-2embed-rnn256-hcnn-2345-1234.npy\n",
      "sum_scores.shape= (217360, 1999)\n",
      "Finished , costed time 989.123 s\n"
     ]
    }
   ],
   "source": [
    "time0 = time.time()\n",
    "scores_names =[\n",
    "    'p1-1-bigru-512.npy',\n",
    "    'p1-2-bigru-512-true.npy',\n",
    "    'textcnn-fc-drop-title-content-256-3457-drop0.5.npy',\n",
    "    'f1-1-cnn-256-23457-11.npy',\n",
    "\n",
    "    'han-cnn-title-content-256-345.npy',\n",
    "    'han-cnn-title-content-256-23457-1234.npy',\n",
    "    'm7-rnn-cnn-256-100.npy',\n",
    "    'p2-1-rnn-cnn-256-256.npy',\n",
    "\n",
    "    'p3-2-cnn-256-2357.npy',\n",
    "    'p3-cnn-512-23457.npy',\n",
    "    'textcnn-fc-drop-title-content-256-345.npy',   \n",
    "    'textcnn-fc-drop-title-content-256-3457-drop0.2.npy',\n",
    "\n",
    "    'm9-han-bigru-title-content-512-30.npy',\n",
    "    'm9-2-han-bigru-title-content-512-30.npy',\n",
    "    'han-bigru-title-content-256-30.npy',\n",
    "    'm8-han-bigru-256-30.npy',\n",
    "\n",
    "    'attention-bigru-title-content-256.npy',\n",
    "    'm7-2-rnn-cnn-128-100.npy',\n",
    "    'textcnn-fc-title-content-256-345.npy',\n",
    "    'm1-2-fasttext-topicinfo.npy',\n",
    "\n",
    "    'ch3-1-cnn-256-2345.npy',\n",
    "    'ch3-2-cnn-256-23457.npy', \n",
    "    'ch4-1-han-bigru-256-52.npy',    \n",
    "    'ch5-1-2embed-rnn256-cnn2345.npy',\n",
    "\n",
    "    'p4-1-han-bigru-256.npy',\n",
    "    'ch6-1-han-cnn-2345-1234.npy',\n",
    "    'p5-1-2embed-rnn256-cnn2345.npy',\n",
    "    'ch5-2-2embed-rnn512-cnn3457.npy',\n",
    "\n",
    "    'c1-1-cnn-max-256-23457.npy',\n",
    "    'c1-2-cnn-256-345710.npy',     \n",
    "    'c2-1-bigru-256.npy',\n",
    "    \n",
    "    'textcnn-fc-drop-title-content-256-345-cross3cross0.npy',\n",
    "    'textcnn-fc-drop-title-content-256-345-cross3cross1.npy',\n",
    "    'textcnn-fc-drop-title-content-256-345-cross3cross2.npy',\n",
    "    'p3-3-cnn-max-256-345710.npy',\n",
    "    'textcnn-title-256-len50.npy',\n",
    "    'ch7-1-2embed-rnn256-hcnn-2345-1234.npy',\n",
    "]  \n",
    "\n",
    "weights = [  9.75938817,   8.63945014,  2.98289344,   3.72323394,   5.04378259,\n",
    "   0.06551187,  -0.79412528,  -0.21665029,   4.90162676,   1.17452791,\n",
    "  -1.46124679,  -0.25384273,   5.50925013,   2.84186738,  -0.93016907,\n",
    "   5.16519035,  -0.47061662,   2.75998217,   2.58152296,  -1.24553333,\n",
    "   2.43288558,   6.17376317,   5.59323762,  10.46123521,   5.29952925,\n",
    "   3.72042086,   5.46707444,   5.51516916,   5.82352659,   1.27847427,\n",
    "  -0.52930247,  -1.99052155,  -3.0938045,   -2.07007845,   4.19963813,\n",
    "   2.10593832,   1.74174258]\n",
    "\n",
    "print(len(scores_names), len(weights))\n",
    "print('All %d models' % len(weights))\n",
    "sum_scores = np.zeros((217360, 1999), dtype=float)\n",
    "scores_path = 'scores/'\n",
    "for i in xrange(len(weights)):\n",
    "    scores_name = scores_names[i]\n",
    "    print('%d/%d, scores_name=%s' %(i+1, len(weights),scores_name))\n",
    "    score = np.load(scores_path + scores_name)\n",
    "    score = softmax(score) # 加归一化\n",
    "    sum_scores = sum_scores + score* weights[i]\n",
    "print('sum_scores.shape=',sum_scores.shape)\n",
    "print('Finished , costed time %g s' % (time.time() - time0))\n",
    "\n",
    "\n",
    "\n",
    "# 写入 result\n",
    "result_path = 'result/submit-best37-softweight-0819.csv'\n",
    "\n",
    "def write_result(sum_scores, result_path):\n",
    "    \"\"\"把结果写到 sum_result.csv 中\"\"\"\n",
    "    print('Begin computing...')\n",
    "    predict_labels_list = map(lambda label: label.argsort()[-1:-6:-1], sum_scores) # 取最大的5个下标\n",
    "    eval_question = np.load('data/eval_question.npy')\n",
    "    with open('data/sr_topic2id.pkl', 'rb') as inp:\n",
    "        sr_topic2id = pickle.load(inp)\n",
    "        sr_id2topic = pickle.load(inp)\n",
    "    pred_labels = np.asarray(predict_labels_list).reshape([-1])\n",
    "    pred_topics = sr_id2topic[pred_labels].values.reshape([-1, 5])   # 转为 topic\n",
    "    df_result = pd.DataFrame({'question':eval_question, 'tid0': pred_topics[:,0], 'tid1':pred_topics[:, 1],\n",
    "                         'tid2': pred_topics[:,2], 'tid3':pred_topics[:,3],'tid4': pred_topics[:,4]})\n",
    "    df_result.to_csv(result_path, index=False, header=False)\n",
    "    print('Finished writing the result')\n",
    "    return df_result\n",
    "\n",
    "time0 = time.time()\n",
    "write_result(sum_scores, result_path)\n",
    "print('Result path %s, costed time %g s' % (result_path, time.time() - time0))"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda root]",
   "language": "python",
   "name": "conda-root-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
